// utils/request.js
const app = getApp()

/**
 * 请求配置
 * @typedef {Object} RequestConfig
 * @property {string} url - 请求地址
 * @property {'GET'|'POST'|'PUT'|'DELETE'|'PATCH'} [method] - 请求方法
 * @property {any} [data] - 请求数据
 * @property {Object} [header] - 请求头
 * @property {number} [timeout] - 超时时间
 * @property {boolean} [showLoading] - 是否显示加载
 * @property {string} [loadingText] - 加载文本
 * @property {boolean} [showError] - 是否显示错误
 * @property {number} [retryCount] - 重试次数
 */

/**
 * API响应数据
 * @typedef {Object} ApiResponse
 * @property {number} code - 状态码
 * @property {string} message - 消息
 * @property {any} data - 数据
 * @property {number} [timestamp] - 时间戳
 */

// HTTP状态码映射
const HTTP_STATUS_MESSAGES = {
  400: '请求参数错误',
  401: '未授权，请重新登录',
  403: '拒绝访问',
  404: '请求的资源不存在',
  405: '请求方法不允许',
  408: '请求超时',
  500: '服务器内部错误',
  502: '网关错误',
  503: '服务不可用',
  504: '网关超时'
}

// 请求管理器类
class RequestManager {
  constructor() {
    this.baseURL = ''
    this.defaultTimeout = 10000
    this.requestInterceptors = []
    this.responseInterceptors = []
    this.errorInterceptors = []
    this.pendingRequests = new Map()
  }

  static getInstance() {
    if (!RequestManager.instance) {
      RequestManager.instance = new RequestManager()
    }
    return RequestManager.instance
  }

  // 设置基础URL
  setBaseURL(url) {
    this.baseURL = url
  }

  // 设置默认超时时间
  setTimeout(timeout) {
    this.defaultTimeout = timeout
  }

  // 添加请求拦截器
  addRequestInterceptor(interceptor) {
    this.requestInterceptors.push(interceptor)
  }

  // 添加响应拦截器
  addResponseInterceptor(interceptor) {
    this.responseInterceptors.push(interceptor)
  }

  // 添加错误拦截器
  addErrorInterceptor(interceptor) {
    this.errorInterceptors.push(interceptor)
  }

  // 生成请求唯一标识
  generateRequestKey(config) {
    return `${config.method || 'GET'}_${config.url}_${JSON.stringify(config.data || {})}`
  }

  // 处理请求拦截器
  async processRequestInterceptors(config) {
    let processedConfig = { ...config }
    for (const interceptor of this.requestInterceptors) {
      processedConfig = await interceptor(processedConfig)
    }
    return processedConfig
  }

  // 处理响应拦截器
  async processResponseInterceptors(response) {
    let processedResponse = { ...response }
    for (const interceptor of this.responseInterceptors) {
      processedResponse = await interceptor(processedResponse)
    }
    return processedResponse
  }

  // 处理错误拦截器
  async processErrorInterceptors(error) {
    let processedError = error
    for (const interceptor of this.errorInterceptors) {
      processedError = await interceptor(processedError)
    }
    return processedError
  }

  // 发起请求
  async request(config) {
    try {
      // 处理请求拦截器
      const processedConfig = await this.processRequestInterceptors(config)
      
      // 构建完整URL
      const fullUrl = processedConfig.url.startsWith('http') 
        ? processedConfig.url 
        : `${this.baseURL}${processedConfig.url}`
      
      // 显示加载提示
      if (processedConfig.showLoading !== false) {
        wx.showLoading({
          title: processedConfig.loadingText || '加载中...',
          mask: true
        })
      }
      
      // 生成请求标识
      const requestKey = this.generateRequestKey(processedConfig)
      
      // 执行请求
      const response = await this.executeRequest(fullUrl, processedConfig, requestKey)
      
      // 隐藏加载提示
      if (processedConfig.showLoading !== false) {
        wx.hideLoading()
      }
      
      // 处理响应拦截器
      const processedResponse = await this.processResponseInterceptors(response)
      
      return processedResponse
    } catch (error) {
      // 隐藏加载提示
      if (config.showLoading !== false) {
        wx.hideLoading()
      }
      
      // 处理错误拦截器
      const processedError = await this.processErrorInterceptors(error)
      
      // 显示错误提示
      if (config.showError !== false) {
        this.showErrorMessage(processedError)
      }
      
      throw processedError
    }
  }

  // 执行具体的请求
  executeRequest(url, config, requestKey) {
    return new Promise((resolve, reject) => {
      const requestTask = wx.request({
        url,
        method: config.method || 'GET',
        data: config.data,
        header: {
          'Content-Type': 'application/json',
          ...config.header
        },
        timeout: config.timeout || this.defaultTimeout,
        success: (res) => {
          this.pendingRequests.delete(requestKey)
          
          // 检查HTTP状态码
          if (res.statusCode >= 200 && res.statusCode < 300) {
            resolve(res.data)
          } else {
            const errorMessage = HTTP_STATUS_MESSAGES[res.statusCode] || `请求失败 (${res.statusCode})`
            reject({
              code: res.statusCode,
              message: errorMessage,
              data: res.data
            })
          }
        },
        fail: (err) => {
          this.pendingRequests.delete(requestKey)
          
          let errorMessage = '网络请求失败'
          
          if (err.errMsg) {
            if (err.errMsg.includes('timeout')) {
              errorMessage = '请求超时'
            } else if (err.errMsg.includes('fail')) {
              errorMessage = '网络连接失败'
            }
          }
          
          reject({
            code: -1,
            message: errorMessage,
            data: null,
            originalError: err
          })
        }
      })
      
      // 保存请求任务
      this.pendingRequests.set(requestKey, requestTask)
    })
  }

  // 显示错误信息
  showErrorMessage(error) {
    const message = error.message || '请求失败'
    wx.showToast({
      title: message,
      icon: 'error',
      duration: 2000
    })
  }

  // 取消所有请求
  cancelAllRequests() {
    this.pendingRequests.forEach((task) => {
      task.abort()
    })
    this.pendingRequests.clear()
  }

  // 取消请求
  cancelRequest(config) {
    const requestKey = this.generateRequestKey(config)
    const task = this.pendingRequests.get(requestKey)
    if (task) {
      task.abort()
      this.pendingRequests.delete(requestKey)
    }
  }

  // GET请求
  get(url, params, config) {
    return this.request({
      url: params ? `${url}?${this.buildQueryString(params)}` : url,
      method: 'GET',
      ...config
    })
  }

  // POST请求
  post(url, data, config) {
    return this.request({
      url,
      method: 'POST',
      data,
      ...config
    })
  }

  // PUT请求
  put(url, data, config) {
    return this.request({
      url,
      method: 'PUT',
      data,
      ...config
    })
  }

  // DELETE请求
  delete(url, config) {
    return this.request({
      url,
      method: 'DELETE',
      ...config
    })
  }

  // PATCH请求
  patch(url, data, config) {
    return this.request({
      url,
      method: 'PATCH',
      data,
      ...config
    })
  }

  // 构建查询字符串
  buildQueryString(params) {
    const searchParams = new URLSearchParams()
    
    Object.keys(params).forEach(key => {
      if (params[key] !== null && params[key] !== undefined) {
        searchParams.append(key, String(params[key]))
      }
    })
    
    return searchParams.toString()
  }

  // 上传文件
  uploadFile(config) {
    return new Promise((resolve, reject) => {
      // 显示加载提示
      if (config.showLoading !== false) {
        wx.showLoading({
          title: config.loadingText || '上传中...',
          mask: true
        })
      }
      
      const fullUrl = config.url.startsWith('http') 
        ? config.url 
        : `${this.baseURL}${config.url}`
      
      wx.uploadFile({
        url: fullUrl,
        filePath: config.filePath,
        name: config.name,
        formData: config.formData,
        header: config.header,
        success: (res) => {
          if (config.showLoading !== false) {
            wx.hideLoading()
          }
          
          try {
            const data = JSON.parse(res.data)
            resolve(data)
          } catch (e) {
            reject({
              code: -1,
              message: '解析响应数据失败',
              data: res.data
            })
          }
        },
        fail: (err) => {
          if (config.showLoading !== false) {
            wx.hideLoading()
          }
          
          reject({
            code: -1,
            message: '上传失败',
            data: null,
            originalError: err
          })
        }
      })
    })
  }

  // 下载文件
  downloadFile(config) {
    return new Promise((resolve, reject) => {
      // 显示加载提示
      if (config.showLoading !== false) {
        wx.showLoading({
          title: config.loadingText || '下载中...',
          mask: true
        })
      }
      
      const fullUrl = config.url.startsWith('http') 
        ? config.url 
        : `${this.baseURL}${config.url}`
      
      wx.downloadFile({
        url: fullUrl,
        header: config.header,
        success: (res) => {
          if (config.showLoading !== false) {
            wx.hideLoading()
          }
          
          if (res.statusCode === 200) {
            resolve({ tempFilePath: res.tempFilePath })
          } else {
            reject({
              code: res.statusCode,
              message: '下载失败',
              data: null
            })
          }
        },
        fail: (err) => {
          if (config.showLoading !== false) {
            wx.hideLoading()
          }
          
          reject({
            code: -1,
            message: '下载失败',
            data: null,
            originalError: err
          })
        }
      })
    })
  }
}

// 创建请求管理器实例
const requestManager = RequestManager.getInstance()

// 添加默认请求拦截器
requestManager.addRequestInterceptor((config) => {
  // 添加认证头
  if (app.globalData.token) {
    config.header = {
      ...config.header,
      'Authorization': `Bearer ${app.globalData.token}`
    }
  }
  
  // 添加设备信息
  const systemInfo = wx.getSystemInfoSync()
  config.header = {
    ...config.header,
    'X-Device-Type': 'miniprogram',
    'X-Device-Platform': systemInfo.platform,
    'X-App-Version': systemInfo.version
  }
  
  return config
})

// 添加默认响应拦截器
requestManager.addResponseInterceptor((response) => {
  // 处理认证失效
  if (response.code === 401) {
    // 清除用户数据
    app.clearUserData()
    
    // 跳转到登录页
    wx.showModal({
      title: '提示',
      content: '登录已过期，请重新登录',
      showCancel: false,
      success: () => {
        wx.redirectTo({
          url: '/pages/login/login'
        })
      }
    })
  }
  
  return response
})

// 添加默认错误拦截器
requestManager.addErrorInterceptor((error) => {
  console.error('请求错误:', error)
  return error
})

// 导出请求方法
const request = {
  // 设置基础URL
  setBaseURL: (url) => requestManager.setBaseURL(url),
  
  // 设置超时时间
  setTimeout: (timeout) => requestManager.setTimeout(timeout),
  
  // 通用请求
  request: (config) => requestManager.request(config),
  
  // GET请求
  get: (url, params, config) => 
    requestManager.get(url, params, config),
  
  // POST请求
  post: (url, data, config) => 
    requestManager.post(url, data, config),
  
  // PUT请求
  put: (url, data, config) => 
    requestManager.put(url, data, config),
  
  // DELETE请求
  delete: (url, config) => 
    requestManager.delete(url, config),
  
  // PATCH请求
  patch: (url, data, config) => 
    requestManager.patch(url, data, config),
  
  // 上传文件
  uploadFile: (config) => 
    requestManager.uploadFile(config),
  
  // 下载文件
  downloadFile: (config) => 
    requestManager.downloadFile(config),
  
  // 取消所有请求
  cancelAll: () => requestManager.cancelAllRequests(),
  
  // 取消特定请求
  cancel: (config) => requestManager.cancelRequest(config),
  
  // 添加拦截器
  addRequestInterceptor: (interceptor) => 
    requestManager.addRequestInterceptor(interceptor),
  
  addResponseInterceptor: (interceptor) => 
    requestManager.addResponseInterceptor(interceptor),
  
  addErrorInterceptor: (interceptor) => 
    requestManager.addErrorInterceptor(interceptor)
}

// 导出模块
module.exports = {
  request,
  RequestManager
}